package ru.usu.gv.utils.test;

import ru.usu.gv.graph.Graph;
import ru.usu.gv.gui.layout.fd.FDEdges;
import ru.usu.gv.gui.layout.fd.ForceDirectedLayoutSettings;
import ru.usu.gv.gui.layout.fd.ForceDirectedLayoutTest;
import ru.usu.gv.gui.layout.fd.StandardForceDirectedLayout;
import ru.usu.gv.utils.GraphAlgorithmHelper;
import ru.usu.gv.utils.generators.BAGenerator;
import ru.usu.gv.utils.math.Matrix;
import ru.usu.gv.utils.math.mds.DistanceScalingTest;

import java.util.HashMap;

/**
 * @author spupyrev
 * 13.06.2010
 */
public class CountIterations
{
	public static void main(String[] argc)
	{
		int dt = 1;
		for (int n = 1; n <= 1000; n += dt)
		{
			dt += 2;
			int sum = 0;
			int nTest = 3;
			if (n < 50)
				nTest = 5;

			for (int t = 0; t < nTest; t++)
			{
				//generate graph
				Graph graph = BAGenerator.generate(n, 3);
				//Graph graph = RandomUtilities.generateRandomTree(n);

				//how many iterations?
				//int iter = iterationsFD(n, graph);
				int iter = iterationsMDS(n, graph);
				sum += iter;
			}

			sum /= nTest;
			System.out.println(n + "     " + sum);
		}
	}

	private static int iterationsFD(int n, Graph graph)
	{
		ForceDirectedLayoutSettings settings = new ForceDirectedLayoutSettings();
		settings.setAttractiveExponent(2);
		settings.setAttractiveFactor(1);
		settings.setRepulsiveExponent(-1.0);
		settings.setRepulsiveFactor(15);
		settings.setIterationLimit(100 * n);
		settings.setDimensions(2);

		FDEdges attractionEdges = new FDEdges();
		FDEdges repulsionEdges = new FDEdges();
		StandardForceDirectedLayout.createEdges(graph, attractionEdges, repulsionEdges);

		int iter = new ForceDirectedLayoutTest(settings).run(attractionEdges, repulsionEdges, new FDEdges(), new HashMap());
		return iter;
	}

	private static int iterationsMDS(int n, Graph graph)
	{
		int[][] dist = new int[n][n];
		GraphAlgorithmHelper.Floyd(graph, dist);
		double a[][] = new double[n][n];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				a[i][j] = dist[i][j];

		Matrix d = new Matrix(a);
		Matrix w = new Matrix(d.getRowCount(), d.getColumnCount());
		for (int i = 0; i < d.getRowCount(); i++)
			for (int j = 0; j < d.getColumnCount(); j++)
				if (d.get(i, j) > 0.0)
				{
					w.set(i, j, 1.0 / (d.get(i, j) * d.get(i, j)));
				}

		int iter = new DistanceScalingTest().mds(d, w, 2, false);
		return iter;
	}
}
